    /*  
    championBuilder - Champions Online character planner.
    Copyright (C) 2009 Moritz Hartmeier
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You can find the GNU General Public License in the data folder.
    */


package ch.zarzu.champions.builder.gui;

import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.HashSet;

import javax.swing.*;

import org.w3c.dom.NodeList;

import ch.zarzu.champions.builder.*;
import ch.zarzu.champions.builder.data.PowerData;
import ch.zarzu.champions.builder.logic.*;
import ch.zarzu.champions.builder.updater.*;
import ch.zarzu.util.*;

public class MainInterface implements MouseListener {
    private static MainInterface instance = null;
    
    private SystemLink sys_link;
    private BuildUpdater updater;
    private Listener listener;
    
    PowerList power_list;
    PowerList frameworks;
    HashMap<String, PowerData> power_data_map;
    LinkedList<String[]> pool_buttons_strings;
    LinkedList<JButton> pool_buttons;
    LinkedList<BuildSheet> build_lists;
    HashMap<String, HashMap<String, PowerData>> advantage_map;
    CharacterSheet char_sheet;
    
    JFrame frame;
    JButton b1, top_label;
    JLayeredPane powerListPane;
    JMenuItem save_menu;
    JLabel top_filler;
    private JScrollPane general_scroll, help_scroll, about_scroll;
    private InfoPane info_pane;
    
    AutoUpdater auto_updater;
    Description description;
    AdvDescription adv_description;
    boolean changed, alternative_pool_active, top_label_locked = false;
    private String app_path;
    
    private HashSet<TabPane> tabs;
    
    
    private MainInterface() {}
    
    public void init() {
        sys_link = SystemLink.getInstance();
        updater = BuildUpdater.getInstance();
        listener = Listener.getInstance();
        
        app_path = AppPath.get();
        
        prepareData();
        assembleGUI();
        startUpdater();
    }
    
    /**
     * get the xml files from the SystemLink and create PowerDatas and PowerListItems out of them
     */
    private void prepareData() {
        updater = BuildUpdater.getInstance();
        
        NodeList xml_pool_list = sys_link.getPools();
        NodeList xml_power_list = sys_link.getPowers();
        NodeList xml_stat_list = sys_link.getStats();
        NodeList xml_talent_list = sys_link.getTalents();
        NodeList xml_build = sys_link.getProgression();
        NodeList xml_frameworks = sys_link.getFrameworks();
        
        //extract the information needed to build the pool list at the top
        pool_buttons_strings = new LinkedList<String[]>();
        String[] s;
        for(int i = 0; i < xml_pool_list.getLength(); i++) {
            String name = xml_pool_list.item(i).getAttributes().getNamedItem("name").getNodeValue();
            String image = xml_pool_list.item(i).getAttributes().getNamedItem("image").getNodeValue();
            if(!image.equals("")) {
                s = new String[5];
                s[0] = app_path + image;
                s[1] = name;
                s[2] = xml_pool_list.item(i).getAttributes().getNamedItem("id").getNodeValue();
                s[3] = "b";
                s[4] = xml_pool_list.item(i).getAttributes().getNamedItem("similar").getNodeValue();
                pool_buttons_strings.add(s);
            }
        }
        
        //initialize the PowerList
        power_list = PowerList.getInstance();
        power_list.init();
        
        //variables used from here on
        LinkedList<String> power_types = new LinkedList<String>();
        HashMap<String, LinkedList<PowerListItem>> power_by_type = new HashMap<String, LinkedList<PowerListItem>>();
        HashMap<String, PowerListItem> power_by_id = new HashMap<String, PowerListItem>();
        power_data_map = new HashMap<String, PowerData>();
        advantage_map = new HashMap<String, HashMap<String, PowerData>>();
        String power_id, advantage_id, framework_id, image, pool_id, power_type;
        Power power;
        Advantage advantage;
        Framework framework;
        PowerData power_data, advantage_data;
        NodeList child_list, grand_child_list;


        //add frameworks
        for(int i = 0; i < xml_frameworks.getLength(); i++) {
            framework_id = xml_frameworks.item(i).getAttributes().getNamedItem("id").getNodeValue();
            image = xml_frameworks.item(i).getAttributes().getNamedItem("path").getNodeValue();
            
            framework = new Framework(image, framework_id);
            power_by_id.put(framework_id, framework);
            
            power_data = new PowerData(xml_frameworks.item(i));
            power_data.subscribe(framework);
            power_data_map.put(framework_id, power_data);
        }
        
        
        //extract the powers, create PowerDatas and Powers, but don't add them yet
        for(int i = 0; i < xml_power_list.getLength(); i++) {
            power_id = xml_power_list.item(i).getAttributes().getNamedItem("id").getNodeValue();
            image = xml_power_list.item(i).getAttributes().getNamedItem("path").getNodeValue();
            
            power = new Power(image, power_id);
            power_by_id.put(power_id, power);
            
            if(power_data_map.containsKey(power_id)) {
                power_data = power_data_map.get(power_id);
                power_data.subscribe(power);
            } else {
                power_data = new PowerData(xml_power_list.item(i));
                power_data.subscribe(power);
                power_data_map.put(power_id, power_data);
            }
            
            //add advantages
            child_list = xml_power_list.item(i).getChildNodes();
            for(int j = 1; j < child_list.getLength(); j += 2) {
                if(child_list.item(j).getNodeName().equals("advantages")) {
                    
                    HashMap<String, PowerData> advantage_list = new HashMap<String, PowerData>();
                    grand_child_list = child_list.item(j).getChildNodes();
                    for(int k = 1; k < grand_child_list.getLength(); k += 2) {
                        advantage_id = grand_child_list.item(k).getAttributes().getNamedItem("id").getNodeValue();
                        advantage = new Advantage(power_id + advantage_id);
                        power_list.addItem(advantage);
                        
                        advantage_data = new PowerData(grand_child_list.item(k));
                        advantage_data.setId(power_id + advantage_id);
                        advantage_data.subscribe(advantage);
                        power_data_map.put(power_id + advantage_id, advantage_data);
                        
                        advantage_list.put(advantage_id, advantage_data);
                    }
                    advantage_map.put(power_id, advantage_list);
                }
            }
        }
        
        //add superstats
        for(int i = 0; i < xml_stat_list.getLength(); i++) {
            power_id = xml_stat_list.item(i).getAttributes().getNamedItem("id").getNodeValue();
            image = xml_stat_list.item(i).getAttributes().getNamedItem("path").getNodeValue();
            
            power = new Power(image, power_id);
            power_by_id.put(power_id, power);
            
            power_data = new PowerData(xml_stat_list.item(i));
            power_data.subscribe(power);
            power_data_map.put(power_id, power_data);
        }
        
        //add talents
        for(int i = 0; i < xml_talent_list.getLength(); i++) {
            power_id = xml_talent_list.item(i).getAttributes().getNamedItem("id").getNodeValue();
            image = xml_talent_list.item(i).getAttributes().getNamedItem("path").getNodeValue();
            
            power = new Power(image, power_id);
            power_by_id.put(power_id, power);
            
            power_data = new PowerData(xml_talent_list.item(i));
            power_data.subscribe(power);
            power_data_map.put(power_id, power_data);
        }
        
        //sort all Powers by type and then add them to the PowerList
        for(int i = 0; i < xml_pool_list.getLength(); i++) {
            pool_id = xml_pool_list.item(i).getAttributes().getNamedItem("id").getNodeValue();
            
            child_list = xml_pool_list.item(i).getChildNodes();
            for(int j = 0; j < child_list.getLength(); j++) {
                if(child_list.item(j).getNodeName().equals("powertype")) {
                    power_type = child_list.item(j).getAttributes().getNamedItem("name").getNodeValue();
                    
                    if(!power_by_type.containsKey(power_type)) {
                        power_by_type.put(power_type, new LinkedList<PowerListItem>());
                        power_types.add(power_type);
                    }
                    
                    grand_child_list = child_list.item(j).getChildNodes();
                    for(int k = 1; k < grand_child_list.getLength(); k += 2) {
                        power_id = grand_child_list.item(k).getAttributes().getNamedItem("id").getNodeValue();
                        
                        if(!power_by_type.get(power_type).contains(power_by_id.get(power_id))) {
                            power_by_type.get(power_type).add(power_by_id.get(power_id));
                        }
                        
                        if(power_data_map.containsKey(power_id)) {
                            power_data_map.get(power_id).addToPool(pool_id);
                            power_data_map.get(power_id).setType(power_type);
                        }
                    }
                }
            }
        }
        
        for(String type : power_types) {
            power_list.addItem(new PowerTypeTag(type));
            for(PowerListItem p : power_by_type.get(type)) {
                power_list.addItem(p);
            }
        }
        
        build_lists = new LinkedList<BuildSheet>();
        build_lists.add(new BuildSheet(xml_build.item(0), "power"));
        build_lists.add(new BuildSheet(xml_build.item(0), "talent"));
        build_lists.add(new BuildSheet(xml_build.item(0), "superstat"));
        
        char_sheet = CharacterSheet.getInstance();
    }
    
    private void assembleGUI() {
        UIManager.put("ToolTip.background", new javax.swing.plaf.ColorUIResource(App.DARK_BLUE));
        UIManager.put("ToolTip.border", BorderFactory.createLineBorder(Color.BLACK, 2));
        ToolTipManager.sharedInstance().setDismissDelay(500000);

        tabs = new HashSet<TabPane>();
        
        JButton button;
        GridBagConstraints c = new GridBagConstraints();
        
        JLayeredPane row1 = new JLayeredPane();
        row1.setLayout(new GridBagLayout());
        
        JLayeredPane column1 = new JLayeredPane();
        SpringLayout layout3 = new SpringLayout();
        column1.setLayout(layout3);
        
        JLayeredPane column2 = new JLayeredPane();
        SpringLayout column2_layout = new SpringLayout();
        column2.setLayout(column2_layout);
        
        JLayeredPane general_pane = new JLayeredPane();
        SpringLayout layout2 = new SpringLayout();
        general_pane.setLayout(layout2);
        
        HelpPane help_pane = new HelpPane();
        help_scroll = new JScrollPane(help_pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        help_scroll.getVerticalScrollBar().setUI(new CustomVerticalScrollBarUI());
        help_scroll.getVerticalScrollBar().setUnitIncrement(20);
        help_scroll.getVerticalScrollBar().setOpaque(false);
        help_scroll.getHorizontalScrollBar().setUI(new CustomHorizontalScrollBarUI());
        help_scroll.getHorizontalScrollBar().setUnitIncrement(20);
        help_scroll.getVerticalScrollBar().setOpaque(false);
        help_scroll.getViewport().setOpaque(false);
        help_scroll.setOpaque(false);
        help_scroll.setBorder(null);
        help_scroll.setWheelScrollingEnabled(true);
        help_scroll.setVisible(false);
        
        AboutPane about_pane = new AboutPane();
        about_scroll = new JScrollPane(about_pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        about_scroll.getVerticalScrollBar().setUI(new CustomVerticalScrollBarUI());
        about_scroll.getVerticalScrollBar().setUnitIncrement(20);
        about_scroll.getVerticalScrollBar().setOpaque(false);
        about_scroll.getHorizontalScrollBar().setUI(new CustomHorizontalScrollBarUI());
        about_scroll.getHorizontalScrollBar().setUnitIncrement(20);
        about_scroll.getHorizontalScrollBar().setOpaque(false);
        about_scroll.getViewport().setOpaque(false);
        about_scroll.setOpaque(false);
        about_scroll.setBorder(null);
        about_scroll.setWheelScrollingEnabled(true);
        about_scroll.setVisible(false);
        
        info_pane = new InfoPane();
        info_pane.setVisible(false);
        
        //scroll pane which encases everything
        general_scroll = new JScrollPane(general_pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        general_scroll.getVerticalScrollBar().setUI(new CustomVerticalScrollBarUI());
        general_scroll.getVerticalScrollBar().setOpaque(false);
        general_scroll.getVerticalScrollBar().setUnitIncrement(20);
        general_scroll.getHorizontalScrollBar().setUI(new CustomHorizontalScrollBarUI());
        general_scroll.getHorizontalScrollBar().setOpaque(false);
        general_scroll.getHorizontalScrollBar().setUnitIncrement(20);
        general_scroll.getViewport().setOpaque(false);
        general_scroll.setOpaque(false);
        general_scroll.setBorder(null);
        general_scroll.setWheelScrollingEnabled(true);
        
        //get the screen resolution to set the size of the window
        int general_scroll_height = 732;
        int general_scroll_width = 1001;
        Dimension screen_dim = Toolkit.getDefaultToolkit().getScreenSize();
        if(screen_dim.height <= 768)
            general_scroll_height = screen_dim.height - 100;
        if(screen_dim.width <= 1000)
            general_scroll_width = screen_dim.width - 20;
        general_scroll.setPreferredSize(new Dimension(general_scroll_width, general_scroll_height));
        
        
        top_label = new JButton("");
        top_label.setFont(new Font("Comic Sans MS", Font.PLAIN, 12));
        top_label.setForeground(Color.WHITE);
        top_label.setBorderPainted(false);
        top_label.setBorder(null);
        top_label.setFocusable(false);
        top_label.setContentAreaFilled(false);
        top_filler = new JLabel();
        
        int j = pool_buttons_strings.size();
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 100.0;
        c.gridx = j;
        row1.add(top_filler, c);
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 0.5;
        c.gridx = j + 1;
        row1.add(top_label,c);
        
        //create buttons for all power lists
        pool_buttons = new LinkedList<JButton>();
        int i = 0;
        int empty_width = 0;
        for(String[] s : pool_buttons_strings){
            ImageIcon icon_tmp = new ImageIcon(s[0] + "b.png");
            ImageIcon icon = new ImageIcon(icon_tmp.getImage().getScaledInstance((int)Math.round(icon_tmp.getIconWidth() * App.SCALE), (int)Math.round(icon_tmp.getIconHeight() * App.SCALE), Image.SCALE_SMOOTH));
            button = new JButton(icon);
            button.setBorderPainted(false);
            button.setBorder(null);
            button.setFocusable(false);
            button.setContentAreaFilled(false);
            button.addMouseListener(this);
            button.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
            c.fill = GridBagConstraints.HORIZONTAL;
            c.weightx = 0.1;
            c.gridx = i;
            c.gridy = 0;
            row1.add(button, c);
            i++;
            pool_buttons.add(button);
            empty_width += icon.getIconWidth();
        }
        setPoolButtonsTooltips();
        
        //fill the rest of the top row
        empty_width = 1000 - empty_width;
        ImageIcon icon_tmp = new ImageIcon(app_path + "images/empty_pool.png");
        ImageIcon icon = new ImageIcon(icon_tmp.getImage().getScaledInstance(empty_width, (int)Math.round(icon_tmp.getIconHeight() * App.SCALE), Image.SCALE_SMOOTH));
        JLabel label = new JLabel(icon);
        label.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
        row1.setMaximumSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
        
        c.fill = GridBagConstraints.BOTH;
        c.gridwidth = 2;
        c.weightx = 100.0;
        c.gridx = i;
        c.gridy = 0;
        row1.add(label, c);
        icon = new ImageIcon(icon_tmp.getImage().getScaledInstance(1000, (int)Math.round(icon_tmp.getIconHeight() * App.SCALE), Image.SCALE_SMOOTH));
        label = new JLabel(icon);
        label.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
        c.gridx = i+i;
        row1.add(label, c);
        
        
        //create power list
        powerListPane = new JLayeredPane();
        powerListPane.setLayout(new GridBagLayout());
        
        //initialize with first list
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.gridwidth = 1;
        c.weighty = 1.0;
        c.gridwidth = 1;
        c.gridx = 0;
        c.gridy = 0;
        
        powerListPane.add(power_list, c);
        
        //scroll pane which encases the power lists
        JScrollPane power_lists_scroll = new JScrollPane(powerListPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        power_lists_scroll.getVerticalScrollBar().setUI(new CustomVerticalScrollBarUI());
        power_lists_scroll.getVerticalScrollBar().setOpaque(false);
        power_lists_scroll.getVerticalScrollBar().setUnitIncrement(20);
        power_lists_scroll.getViewport().setOpaque(false);
        power_lists_scroll.setOpaque(false);
        power_lists_scroll.setBorder(null);
        power_lists_scroll.setWheelScrollingEnabled(true);
        power_lists_scroll.setPreferredSize(new Dimension(362, 380));
        column1.add(power_lists_scroll);
        
        SearchPane search_pane = SearchPane.getInstance();
        column1.add(search_pane);
        
        //descriptions
        description = new Description();
        adv_description = new AdvDescription();
        
        TabPane description_tab;
        LinkedList<JLayeredPane> description_tabs = new LinkedList<JLayeredPane>();
        JLayeredPane description_pane;
        SpringLayout description_layout;
        
        //scroll pane which encases the description
        LinkedList<String> description_tags = new LinkedList<String>();
        description_tags.add("text");
        description_tags.add("advanced");
        JScrollPane description_scroll;
        for(String s : description_tags) {
            if(s.equals("text"))
                description_scroll = new JScrollPane(description, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            else
                description_scroll = new JScrollPane(adv_description, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            description_scroll.getVerticalScrollBar().setUI(new CustomVerticalScrollBarUI());
            description_scroll.getVerticalScrollBar().setOpaque(false);
            description_scroll.getVerticalScrollBar().setUnitIncrement(20);
            description_scroll.getViewport().setOpaque(false);
            description_scroll.setOpaque(false);
            description_scroll.setBorder(null);
            description_scroll.setWheelScrollingEnabled(true);
            
            description_pane = new JLayeredPane();
            description_layout = new SpringLayout();
            description_pane.setLayout(description_layout);
            description_pane.add(description_scroll);
            description_pane.setName(s);

            description_layout.putConstraint(SpringLayout.EAST, description_pane, 0, SpringLayout.EAST, description_scroll);
            description_layout.putConstraint(SpringLayout.SOUTH, description_pane, 0, SpringLayout.SOUTH, description_scroll);
            description_tabs.add(description_pane);
        }
        description_tab = new TabPane(description_tabs);
        description_tab.setPreferredSize(new Dimension(361, 325));
        
        column1.add(description_tab);
        tabs.add(description_tab);
        
        //search, powerlist and description into column1
        layout3.putConstraint(SpringLayout.EAST, search_pane, 250, SpringLayout.WEST, column1);
        layout3.putConstraint(SpringLayout.SOUTH, search_pane, 20, SpringLayout.NORTH, column1);
        layout3.putConstraint(SpringLayout.WEST, search_pane, 0, SpringLayout.WEST, column1);
        layout3.putConstraint(SpringLayout.WEST, power_lists_scroll, 0, SpringLayout.WEST, column1);
        layout3.putConstraint(SpringLayout.NORTH, power_lists_scroll, 5, SpringLayout.SOUTH, search_pane);
        layout3.putConstraint(SpringLayout.EAST, description_tab, 0, SpringLayout.EAST, power_lists_scroll);
        layout3.putConstraint(SpringLayout.WEST, description_tab, 0, SpringLayout.WEST, column1);
        layout3.putConstraint(SpringLayout.NORTH, description_tab, 10, SpringLayout.SOUTH, power_lists_scroll);
        layout3.putConstraint(SpringLayout.EAST, column1, 0, SpringLayout.EAST, power_lists_scroll);
        layout3.putConstraint(SpringLayout.SOUTH, column1, 0, SpringLayout.SOUTH, description_tab);
        
        
        //powers in build
        LinkedList<JLayeredPane> build_list = new LinkedList<JLayeredPane>();
        for(BuildSheet b : build_lists) {
            build_list.add((JLayeredPane) b);
        }
        TabPane build_tab = new TabPane(build_list);
        build_tab.setPreferredSize(new Dimension(360, 667));
        
        column2.add(build_tab);
        tabs.add(build_tab);
        column2_layout.putConstraint(SpringLayout.EAST, column2, 0, SpringLayout.EAST, build_tab);
        column2_layout.putConstraint(SpringLayout.SOUTH, column2, 0, SpringLayout.SOUTH, build_tab);
        
        
        //character sheet
        char_sheet.setPreferredSize(new Dimension(250, 100));
        
        //add column and row panes to root pane
        general_pane.add(row1);
        general_pane.add(column1);
        general_pane.add(column2);
        general_pane.add(char_sheet);
        
        //column1, column2 and row1 into general_pane
        layout2.putConstraint(SpringLayout.WEST, row1, 0, SpringLayout.WEST, general_pane);
        layout2.putConstraint(SpringLayout.NORTH, row1, 0, SpringLayout.NORTH, general_pane);
        layout2.putConstraint(SpringLayout.SOUTH, column1, 0, SpringLayout.SOUTH, column2);
        layout2.putConstraint(SpringLayout.WEST, column1, 5, SpringLayout.WEST, general_pane);
        layout2.putConstraint(SpringLayout.NORTH, column1, 0, SpringLayout.SOUTH, row1);
        layout2.putConstraint(SpringLayout.WEST, column2, 6, SpringLayout.EAST, column1);
        layout2.putConstraint(SpringLayout.NORTH, column2, 0, SpringLayout.SOUTH, row1);
        layout2.putConstraint(SpringLayout.WEST, char_sheet, 12, SpringLayout.EAST, column2);
        layout2.putConstraint(SpringLayout.SOUTH, char_sheet, -5, SpringLayout.SOUTH, column2);
        layout2.putConstraint(SpringLayout.NORTH, char_sheet, 0, SpringLayout.SOUTH, row1);
        layout2.putConstraint(SpringLayout.EAST, general_pane, 5, SpringLayout.EAST, char_sheet);
        layout2.putConstraint(SpringLayout.SOUTH, general_pane, 5, SpringLayout.SOUTH, column2);
    }
    
    private void startUpdater() {
        //initialize BuildUpdater
        updater.initialize(power_data_map, advantage_map, build_lists, description, adv_description);
        
        HashSet<String> pool_ids = new HashSet<String>();
        for(String[] s : pool_buttons_strings)
            pool_ids.add(s[2]);
        
        listener.selectPools(pool_ids);
    }
    
    private void setPoolButtonsTooltips() {
        for(int i = 0; i < pool_buttons.size(); i++) {
            pool_buttons.get(i).setToolTipText("<html><span style='font-family:Comic Sans MS;font-size:100%;color:white'>" + sys_link.translate(pool_buttons_strings.get(i)[1]) + "</span></html>");
        }
    }
    
    private void setPoolButton(int i, boolean b) {
        JButton button = pool_buttons.get(i);
        String[] s = pool_buttons_strings.get(i);
        
        String variant = b ? "b" : "a";
        
        pool_buttons_strings.get(i)[3] = variant;
        ImageIcon icon_tmp = new ImageIcon(s[0] + variant + ".png");
        ImageIcon icon = new ImageIcon(icon_tmp.getImage().getScaledInstance((int)Math.round(icon_tmp.getIconWidth() * App.SCALE), (int)Math.round(icon_tmp.getIconHeight() * App.SCALE), Image.SCALE_SMOOTH));
        button.setIcon(icon);
        
        i++;
    }
    
    public void clearPoolButtons() {
        for(int i = 0; i < pool_buttons.size(); i++) {
            setPoolButton(i, false);
        }
    }
    
    public void setPool(String id) {
        for(int i = 0; i < pool_buttons_strings.size(); i++) {
            if(pool_buttons_strings.get(i)[2].equals(id))
                setPoolButton(i, true);
        }
    }
    
    //mouse events of pool buttons
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {
        JButton source = null;
        int i = 0;
        for(JButton b : pool_buttons) {
            if(e.getSource() == b) {
                source = b;
                break;
            }
            i++;
        }
        String[] strings = pool_buttons_strings.get(i);
        if(source != null) {
            HashSet<String> pool_ids = new HashSet<String>();
            if(e.getButton() == MouseEvent.BUTTON1) {
                //set a group active
                if(e.getClickCount() == 2) {
                    clearPoolButtons();
                    
                    pool_ids.add(strings[2]);
                    setPoolButton(i, true);
                    if(!strings[4].equals("")) {
                        for(String similar : strings[4].split("[,]")) {
                            pool_ids.add(similar);
                            setPool(similar);
                        }
                    }
                    listener.selectPools(pool_ids);
                
                //only set the clicked one
                } else {
                    pool_ids.add(strings[2]);
                    clearPoolButtons();
                    setPoolButton(i, true);
                    
                    listener.selectPools(pool_ids);
                }
                
            } else if(e.getButton() == MouseEvent.BUTTON3) {
                //set all pools active
                if(e.getClickCount() == 2) {
                    for(int j = 0; j < pool_buttons_strings.size(); j++) {
                        pool_ids.add(pool_buttons_strings.get(j)[2]);
                        setPoolButton(j, true);
                    }
                    listener.selectPools(pool_ids);
                    
                //add or remove the clicked one
                } else {
                    pool_ids.add(strings[2]);
                    setPoolButton(i, strings[3].equals("a"));
                    
                    listener.addPools(pool_ids);
                }
            }
        }
    }
    
    public void setTopText(String text, int type) {
        if(!top_label_locked) {
            if(text.length() > 60)
                text = text.substring(0, 37) + "...";
            top_label.setText(text + "   ");
            //make the label into a button for updating or downloading
            if(type != 0) {
                top_label.setFont(new Font("Comic Sans MS", Font.BOLD, 12));
                top_label.setForeground(Color.RED);
                top_label.addActionListener(listener);
                top_label_locked = true;
                if(type == 1)
                    top_label.setActionCommand("update");
                else
                    top_label.setActionCommand("download");
            }
        }
    }
    
    /**
     * the build changed, mark it
     */
    public void setChanged(boolean c) {
        changed = c;
        if(c) {
            Main.getInstance().save_menu.setEnabled(true);
            setTopText(sys_link.translate("ctrl_s"), 0);
        } else
            Main.getInstance().save_menu.setEnabled(false);
    }
    
    public boolean isChanged() {
        return changed;
    }
    
    public void openHelp() {
        HelpPane h = (HelpPane) help_scroll.getViewport().getComponent(0);
        h.redraw();
        
        info_pane.setVisible(false);
        help_scroll.setVisible(true);
        about_scroll.setVisible(false);
        general_scroll.setVisible(false);
    }
    
    public void openAbout() {
        AboutPane h = (AboutPane) about_scroll.getViewport().getComponent(0);
        h.redraw();

        info_pane.setVisible(false);
        help_scroll.setVisible(false);
        about_scroll.setVisible(true);
        general_scroll.setVisible(false);
    }
    
    public void openInfo() {
        info_pane.redraw("changing language - please wait");
        
        info_pane.setVisible(true);
        help_scroll.setVisible(false);
        about_scroll.setVisible(false);
        general_scroll.setVisible(false);
    }
    
    public void backToMain() {
        info_pane.setVisible(false);
        help_scroll.setVisible(false);
        about_scroll.setVisible(false);
        general_scroll.setVisible(true);
    }
    
    public LinkedList<Component> getComponents() {
        LinkedList<Component> list = new LinkedList<Component>();
        list.add(info_pane);
        list.add(help_scroll);
        list.add(about_scroll);
        list.add(general_scroll);
        
        return list;
    }
    
    public void updateLanguage() {
        for(TabPane tab : tabs) {
            tab.updateLanguage();
        }
        setPoolButtonsTooltips();
    }
    
    public static MainInterface getInstance() {
        if(instance == null)
            instance = new MainInterface();
        return instance;
    }
}
